﻿/*
 * ========================================================================
 * Copyright(c) 2007-2012 情留メ蚊子, All Rights Reserved.
 * Welcom use the LiteFetion.
 * See more information,Please goto http://www.94qing.com
 * ========================================================================
 * 
 * 作 者：情留メ蚊子
 * Q  Q: 540644769
 * 邮 箱：qlwz@qq.com
 * 网 址：http://www.94qing.com
 * ========================================================================
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using LiteFetion.Model;
using LiteFetion.Utils;
using Newtonsoft.Json.Linq;

namespace LiteFetion
{
    /// <summary>
    /// 好友管理
    /// </summary>
    public class BuddyManager
    {
        public BuddyManager(FetionClient client)
        {
            FetionClient = client;
        }

        /// <summary>
        /// FetionClient
        /// </summary>
        public FetionClient FetionClient { get; private set; }

        /// <summary>
        /// User
        /// </summary>
        public User User { get { return FetionClient.User; } }


        /// <summary>
        /// 处理添加好友的请求
        /// </summary>
        /// <param name="buddy">发起请求的好友</param>
        /// <param name="isAgree">是否同意，如果同意，默认添加到默认分组</param>
        /// <param name="localName">如果同意，可以设置本地显示的名字； 如果不同意，直接传递null即可</param>
        /// <param name="cord">如果同意，添加好友的分组列表； 如果不同意，直接传递null即可</param>
        /// <returns></returns>
        public ActionResult BuddyAgreeInvite(Buddy buddy, bool isAgree, string localName, Cord cord)
        {
            if (buddy == null)
            {
                return ActionResult.WRONG_PARAM;
            }
            string postData = string.Format("ssid={0}&BuddyId={1}&Result={2}&BuddyList={3}&LocalName={4}",
                this.User.SessionId, buddy.UserId, isAgree ? 1 : 0, cord == null ? 0 : cord.Id, localName == null ? "" : localName);
            HttpHelper http = new HttpHelper();
            http.Url = Gobal.WEBIM_URL_HANDLE_ADD_BUDDY.FormatWith(this.FetionClient.RequestVersion++);
            http.Method = Method.POST;
            http.PostData = postData;
            http.Cookies = this.User.Cookies;
            http.Do();

            this.FetionClient.Debug(http);

            if (http.StatusCode != HttpStatusCode.OK)
            {
                return ActionResult.HTTP_FAILED;
            }
            JObject json = Util.GetObjectResult(http.Html);
            if (json == null)
            {
                return ActionResult.JSON_FAILED;
            }
            int status = json.Value<int>("rc");
            if (status != 200)
            {
                return ActionResult.REQUEST_FAILED;
            }
            if (isAgree)
            {
                buddy.Relation = Relation.BUDDY;
            }
            else
            {
                this.FetionClient.BuddyList.Remove(buddy);
            }
            return ActionResult.SUCCESS;
        }

        /// <summary>
        /// 添加好友，需要首先获取验证码,验证码的类型为VerifyImage.TYPE_ADD_BUDDY
        /// </summary>
        /// <param name="account">飞信号或者手机号</param>
        /// <param name="desc">对自己的说明(我是{$desc})</param>
        /// <param name="localName">设置显示本地姓名</param>
        /// <param name="cord">所属分组，如果为null添加到默认分组</param>
        /// <param name="verifyImage">验证码，验证码的类型为VerifyImage.TYPE_ADD_BUDDY，需要首先获取</param>
        /// <returns></returns>
        public ActionResult AddBuddy(string account, string desc, string localName, Cord cord, VerifyImage verifyImage)
        {
            string postData = string.Format("ssid={0}&AddType={1}&UserName={2}&Desc={3}&LocalName={4}&Ccp={5}&CcpId={6}&BuddyLists={7}&PhraseId={8}&SubscribeFlag={9}",
                this.User.SessionId,
                account.Length == 11 ? 1 : 0,
                account,
                desc == null ? "" : desc,
                localName == null ? "" : localName,
                verifyImage.VerifyCode,
                verifyImage.SessionId,
                cord == null ? 0 : cord.Id,
                0,
                0
                );

            HttpHelper http = new HttpHelper();
            http.Url = Gobal.WEBIM_URL_ADD_BUDDY.FormatWith(this.FetionClient.RequestVersion++);
            http.Method = Method.POST;
            http.PostData = postData;
            http.Cookies = this.User.Cookies;
            http.Do();

            this.FetionClient.Debug(http);

            if (http.StatusCode != HttpStatusCode.OK)
            {
                return ActionResult.HTTP_FAILED;
            }
            JObject json = Util.GetObjectResult(http.Html);
            if (json == null)
            {
                return ActionResult.JSON_FAILED;
            }
            int status = json.Value<int>("rc");
            switch (status)
            {
                case 200:
                    json = json.Value<JObject>("rv");
                    Buddy buddy = new Buddy();
                    buddy.Uri = json.Value<string>("uri");
                    buddy.UserId = json.Value<int>("uid");
                    buddy.IsBlack = false;
                    buddy.LocalName = json.Value<string>("ln");
                    buddy.Relation = Relation.UNCONFIRMED;
                    this.FetionClient.BuddyList.Add(buddy);
                    return ActionResult.SUCCESS;
                case 312:
                    return ActionResult.VERIFY_FAILED;
                case 404:
                    return ActionResult.USER_NOT_FOUND;
                case 521:
                    return ActionResult.BUDDY_EXISTS;
                default:
                    return ActionResult.REQUEST_FAILED;
            }
        }

        /// <summary>
        /// 移出黑名单
        /// </summary>
        /// <param name="buddy">好友对象</param>
        /// <returns></returns>
        public ActionResult RemoveBlackBuddy(Buddy buddy)
        {
            return OpBuddy(buddy, false);
        }

        /// <summary>
        /// 加入黑名单
        /// </summary>
        /// <param name="buddy">好友对象</param>
        /// <returns></returns>
        public ActionResult AddBlackBuddy(Buddy buddy)
        {
            return OpBuddy(buddy, true);
        }

        /// <summary>
        /// 黑名单操作
        /// </summary>
        /// <param name="buddy">好友对象</param>
        /// <param name="op"></param>
        /// <returns></returns>
        private ActionResult OpBuddy(Buddy buddy, bool op)
        {
            if (buddy == null)
            {
                return ActionResult.WRONG_PARAM;
            }
            string postData = string.Format("ssid={0}&Op={1}&To={2}", this.User.SessionId, op ? 1 : 2, buddy.UserId);

            HttpHelper http = new HttpHelper();
            http.Url = Gobal.WEBIM_URL_OP_BUDDY.FormatWith(this.FetionClient.RequestVersion++);
            http.Method = Method.POST;
            http.PostData = postData;
            http.Cookies = this.User.Cookies;
            http.Do();

            this.FetionClient.Debug(http);

            if (http.StatusCode != HttpStatusCode.OK)
            {
                return ActionResult.HTTP_FAILED;
            }
            JObject json = Util.GetObjectResult(http.Html);
            if (json == null)
            {
                return ActionResult.JSON_FAILED;
            }
            int status = json.Value<int>("rc");
            switch (status)
            {
                case 200:
                    buddy.IsBlack = op;
                    return ActionResult.SUCCESS;
                case 312:
                    return ActionResult.VERIFY_FAILED;
                case 404:
                    return ActionResult.USER_NOT_FOUND;
                case 521:
                    return ActionResult.BUDDY_EXISTS;
                default:
                    return ActionResult.REQUEST_FAILED;
            }
        }

        #region 查询好友操作
        /// <summary>
        /// 自动匹配返回好友对象
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public Buddy GetBuddy(object obj)
        {
            Buddy buddy = null;
            if (obj is int)
            {
                buddy = GetBuddyByUserId((int)obj);
                if (buddy != null) return buddy;
                buddy = GetBuddyBySid((int)obj);
                if (buddy != null) return buddy;
                buddy = GetBuddyByMobile(obj.ToString());
                if (buddy != null) return buddy;
            }
            else if (obj is string)
            {
                buddy = GetBuddyByUri((string)obj);
                if (buddy != null) return buddy;
            }
            return buddy;
        }

        /// <summary>
        /// 根据用户编号返回好对象
        /// </summary>
        /// <param name="userId">用户编号</param>
        /// <returns></returns>
        public Buddy GetBuddyByUserId(int userId)
        {
            return this.FetionClient.BuddyList.FirstOrDefault(p => p.UserId == userId);
        }

        /// <summary>
        /// 根据用户uri返回好友对象
        /// </summary>
        /// <param name="uri">uri</param>
        /// <returns></returns>
        public Buddy GetBuddyByUri(string uri)
        {
            return this.FetionClient.BuddyList.FirstOrDefault(p => p.Uri.Compare(uri));
        }

        /// <summary>
        /// 根据用户sid返回好友对象
        /// </summary>
        /// <param name="sid">sid</param>
        /// <returns></returns>
        public Buddy GetBuddyBySid(int sid)
        {
            return this.FetionClient.BuddyList.FirstOrDefault(p => p.Sid == sid);
        }

        /// <summary>
        /// 根据用户手机返回好友对象
        /// </summary>
        /// <param name="mobile">手机号</param>
        /// <returns></returns>
        public Buddy GetBuddyByMobile(string mobile)
        {
            return this.FetionClient.BuddyList.FirstOrDefault(p => p.Mobile.Compare(mobile));
        }

        /// <summary>
        /// 获取黑名单的好友列表
        /// </summary>
        /// <returns></returns>
        public List<Buddy> GetBlackList()
        {
            return this.FetionClient.BuddyList.FindAll(p => p.IsBlack);
        }

        /// <summary>
        /// 获取陌生人的好友列表
        /// </summary>
        /// <returns></returns>
        public List<Buddy> GetStrangerList()
        {
            return this.FetionClient.BuddyList.FindAll(p => p.Relation == Relation.STRANGER);
        }

        /// <summary>
        /// 获取指定分组好友列表
        /// </summary>
        /// <param name="id">分组Id</param>
        /// <returns></returns>
        public List<Buddy> GetBuddyListByCord(int id)
        {
            Cord cord = this.FetionClient.CordList.FirstOrDefault(p => p.Id == id);
            return GetBuddyListByCord(cord);
        }

        /// <summary>
        /// 获取指定分组好友列表
        /// </summary>
        /// <param name="cord">分组</param>
        /// <returns></returns>
        public List<Buddy> GetBuddyListByCord(Cord cord)
        {
            if (cord == null)
            {
                return null;
            }
            string id = cord.Id.ToString();
            return this.FetionClient.BuddyList.FindAll((p) =>
            {
                return p.CordIds != null && (p.CordIds.Compare(id) || p.CordIds.StartsWith(id + ";") || p.CordIds.EndsWith(";" + id) || p.CordIds.IndexOf(";" + id + ";") > 0);
            });
        }

        /// <summary>
        /// 获取没有分组的好友列表，在客户端里就是默认的分组列表中的好友
        /// </summary>
        /// <returns></returns>
        public List<Buddy> GetBuddyListWithoutCord()
        {
            return this.FetionClient.BuddyList.FindAll(p => p.CordIds.IsEmpty());
        }
        #endregion
    }
}
